简述:
《Java 编程思想》 P718 ~ P722
模拟死锁的场景, 三个人 三根筷子,每个人需要拿到身边的两根筷子才能开始吃饭
出现死锁的场景是,三个人都拿到了右边的筷子,但是由于筷子都被抢占,均无法获得左边的筷子
Chopstick.java
package com.anialy.test.multithread.philosophers;
public class Chopstick {
private boolean taken = false;
public synchronized void take() throws InterruptedException{
while(taken)
wait();
taken = true;
}
public synchronized void drop(){
taken = false;
}
}
Philosopher.java
package com.anialy.test.multithread.philosophers;
import java.util.concurrent.TimeUnit;
public class Philosopher implements Runnable {
private Chopstick left; // 左边的筷子
private Chopstick right; // 右边的筷子
public Philosopher(Chopstick left, Chopstick right){
this.left = left;
this.right = right;
}
private void pause() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(100);
}
private void pauseToHoldChopstick() throws InterruptedException {
TimeUnit.MILLISECONDS.sleep(1000);
}
public void run() {
try {
while(!Thread.interrupted()) {
System.out.println(this + " thinking");
pause();
right.take();
System.out.println(this + " grabbing right");
// 当一个人拿起了一根筷子, 停顿一段时间,让别人也抢到各自右边的筷子
pauseToHoldChopstick();
left.take();
System.out.println(this + " grabbing left");
System.out.println(this + " eating");
pause();
// 完成之后放下筷子
right.drop();
System.out.println(this + " drop right");
left.drop();
System.out.println(this + " drop left");
}
} catch (InterruptedException e){
System.out.println(this + " exiting via interrupt");
}
}
}
死锁测试函数
DeadLockTest.java
package com.anialy.test.multithread.philosophers;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class DeadLockTest {
public static void main(String[] args) throws InterruptedException, IOException {
int size = 3;
ExecutorService exec = Executors.newCachedThreadPool();
Chopstick[] sticks = new Chopstick[size];
for(int i=0; i<size; i++)
sticks[i] = new Chopstick();
for(int i=0; i<size; i++)
exec.execute(new Philosopher(sticks[i]
, sticks[(i+1) % size]));
TimeUnit.SECONDS.sleep(50);
// 关掉所有的线程
exec.shutdownNow();
}
}
测试如图,在每个线程拿到右边的筷子之后,都进入死锁等待状态